1 //-------------------------------------------------------------------------------------------------
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // Smallest possible implementation of an exclusive lock.
7 //-------------------------------------------------------------------------------------------------
14 volatile DWORD m_dwOwner
; // Owning thread (non-zero means locked)
16 void Spin (long *piSpinCount
)
18 if ((*piSpinCount
)-- < 0)
20 InterlockedIncrement (&m_iSleeps
);
22 *piSpinCount
= m_iSpinStart
;
24 else if (*piSpinCount
== (m_iSpinStart
- 1))
26 InterlockedIncrement (&m_iSpins
);
32 static LONG m_iSleeps
;
33 static LONG m_iSpinStart
;
36 CTinyLock() : m_dwOwner(0)
38 if (m_iSpinStart
== -1)
42 if (si
.dwNumberOfProcessors
> 1)
43 m_iSpinStart
= 4000; // Hard-coded spin count...
49 ////////////////////////////////////////////////////////////////////////////
50 // CTinyLock::Acquire -- lock this object, returning true if this is the
51 // first lock, false otherwise. If true is returned, Release() must be
52 // called to unlock the object.
56 long iSpin
= m_iSpinStart
;
57 DWORD dwOld
, dwTid
= GetCurrentThreadId();
61 dwOld
= (DWORD
)InterlockedCompareExchange ((LONG
*) & m_dwOwner
, (LONG
)dwTid
, 0);
62 if (dwOld
== 0 || dwOld
== dwTid
)
70 ////////////////////////////////////////////////////////////////////////////
71 // CTinyLock::Release -- release the lock held by this thread. This should
72 // NOT be called if Acquire() returned false, indicating that this thread
73 // already had this object locked.
77 VSASSERT (m_dwOwner
== GetCurrentThreadId(), "Invalid");
81 ////////////////////////////////////////////////////////////////////////////
82 // CTinyLock::LockedByMe -- tests the lock to see if this thread currently
86 return m_dwOwner
== GetCurrentThreadId();
89 int CountLockedByMe ()
91 return m_dwOwner
== GetCurrentThreadId() ? 1 : 0;
94 ////////////////////////////////////////////////////////////////////////////
95 // CTinyLock::IsLocked -- tests the lock to see if it is locked or not (by
100 return m_dwOwner
!= 0;
103 ////////////////////////////////////////////////////////////////////////////////
106 // This is a friendly way to give up a time slice. It uses Sleep(1), which
107 // allows lower-priority threads to execute, and then calls PeekMessage, which
108 // allows sent messages to be processed by this thread (allowing COM/RPC messages
109 // to go through, etc.)
110 static inline void Snooze ()
112 // #ifndef FEATURE_PAL
115 // PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
122 ////////////////////////////////////////////////////////////////////////////////
123 // CTinyGate -- handles scope-locking for a CTinyLock object
132 CTinyGate(CTinyLock
*p
) : m_pLock(p
)
134 m_fLocked
= m_pLock
&& m_pLock
->Acquire();
153 VSASSERT(!m_fLocked
, "Invalid");
154 m_fLocked
= m_pLock
&& m_pLock
->Acquire();
157 bool HasLocked() const